package com.fingard.dsp.bank.directbank.cgb02;

import cfca.sadk.cgb.toolkit.BASE64Toolkit;
import cfca.sadk.cgb.toolkit.SM2Toolkit;
import com.fingard.constant.Format;
import com.fingard.dsp.bank.directbank.DirectBase;
import com.fingard.dsp.bank.directbank.cgb02.util.HttpConnUtil;
import com.fingard.io.FileHelper;
import com.fingard.net.ITcpClient;
import com.fingard.net.TcpPortClient;
import com.fingard.net.TcpReceiver;
import com.fingard.util.HttpClientUtil;
import com.fingard.util.TransIDHelper;
import com.fingard.xml.XmlTextWriter;

import java.security.PrivateKey;
import java.util.Date;

public class CGB02Base extends DirectBase implements ITcpClient {
	private static TransIDHelper idHelper = new TransIDHelper(1, 999);

	protected String getQryTransID() {
		Date tmpDateNow = new Date();
		return Format.DateTime12Year2Format.format(tmpDateNow) + idHelper.getNextIDStr();
	}

	protected String getCharset() {
		return getBankConfig().getCharset("GBK");
	}

	protected void writeCommonHeader(XmlTextWriter xmlWriter, CGB02Header p_bankHeader) throws Exception {
		Date tmpDateNow = new Date();
		xmlWriter.writeStartDocByDeclaration("<?xml version=\"1.0\" encoding=\"" + getCharset() + "\" ?>");
		xmlWriter.writeStartElement("BEDC");
		xmlWriter.writeStartElement("Message");
		xmlWriter.writeStartElement("commHead");
		xmlWriter.writeElementString("tranCode", p_bankHeader.transCode);
		xmlWriter.writeElementString("cifMaster", bankFront.org);// 客户号
		xmlWriter.writeElementString("entSeqNo", p_bankHeader.reqSeqID);
		xmlWriter.writeElementString("tranDate", Format.Date8Format.format(tmpDateNow));
		xmlWriter.writeElementString("tranTime", Format.Time6Format.format(tmpDateNow));
		xmlWriter.writeElementClosed("retCode");
		xmlWriter.writeElementString("entUserId", bankFront.operator);// 操作员号
		xmlWriter.writeElementString("password", bankFront.loginPasswd);
		xmlWriter.writeEndElement();
	}

	/**
	 * 去前置机发送银行
	 *
	 * @param p_reqStr
	 * @return
	 * @throws Exception
	 */
	protected String[] sendToBank(String p_reqStr) throws Exception {
		String[] retStr = new String[] { "", "" };
		String sendMethd = getValueAsString("postByHttp");
		if ("1".equals(sendMethd)) {
			return sendToBankByHttps(p_reqStr);
		} else {
			WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP + ":" + bankFront.serverPort);
			// 发送银行前置
			TcpPortClient tmpClient = new TcpPortClient(bankFront.serverIP, Integer.parseInt(bankFront.serverPort), this);
			String tmpCharset = getCharset();

			String interactiveMode = getBankConfig().getValueAsString("interactiveMode");
			if ("no-terminal".equals(interactiveMode)) {
				// 签名
				int indexPre = p_reqStr.indexOf("<Message>");
				int indexPrefix = p_reqStr.indexOf("</Message>");
				String waitSignData = p_reqStr.substring(indexPre, indexPrefix + 10);
				String ownCertFilePath = com.fingard.dsp.DSPSet.replaceFilePath(getBankConfig().getValueAsString("ownCertFilePath")).replaceAll("\r|\n|\t", "");
				String signature = sm2WithSM3(ownCertFilePath, waitSignData);
				p_reqStr = p_reqStr.replace("</BEDC>", "<Signature><signatureMethod>SM2</signatureMethod><digestMethod>SM3</digestMethod><signedInfo>" + signature + "</signedInfo></Signature></BEDC>");
			}

			byte[] tmpBytesBody = p_reqStr.getBytes(tmpCharset);
			WriteBankLogStep2(p_reqStr);
			TcpReceiver tmpReceiver = tmpClient.sendMessage(tmpBytesBody);
			retStr[0] = tmpReceiver.connState;
			if (tmpReceiver.recBytes != null) {
				retStr[1] = new String(tmpReceiver.recBytes, 0, tmpReceiver.readedLength, tmpCharset);
				WriteBankLogStep3(retStr[1]);
			} else {
				retStr[1] = tmpReceiver.getConnMsg();
			}
			if (!tmpReceiver.isCompleted) {
				WriteBankLogLn(tmpReceiver.getConnMsg());
			}
			return retStr;
		}
	}

	/**
	 * SM2-SM3加密算法
	 *
	 * @param actItem
	 * @param signData
	 * @return
	 * @throws Exception
	 */
	public static String sm2WithSM3(String signData, String ownKeyStorePath) throws Exception {
		String keyMsg = FileHelper.readFileText(ownKeyStorePath, "GBK");
		SM2Toolkit tool = new SM2Toolkit();
		PrivateKey privateKey = tool.SM2BuildPrivateKey(keyMsg);
		byte[] signature = tool.SM2Sign(privateKey, signData.getBytes("GBK"));
		return BASE64Toolkit.encode(signature);
	}

	protected String[] sendToBankByHttps(String p_reqStr) throws Exception {
		WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP);

		String interactiveMode = getBankConfig().getValueAsString("interactiveMode");
		if ("no-terminal".equals(interactiveMode)) {
			// 签名
			int indexPre = p_reqStr.indexOf("<Message>");
			int indexPrefix = p_reqStr.indexOf("</Message>");
			String waitSignData = p_reqStr.substring(indexPre, indexPrefix + 10);
			String ownCertFilePath = com.fingard.dsp.DSPSet.replaceFilePath(getBankConfig().getValueAsString("ownCertFilePath")).replaceAll("\r|\n|\t", "");
			String signature = sm2WithSM3(waitSignData, ownCertFilePath);
			p_reqStr = p_reqStr.replace("</BEDC>", "<Signature><signatureMethod>SM2</signatureMethod><digestMethod>SM3</digestMethod><signedInfo>" + signature + "</signedInfo></Signature></BEDC>");
		}
		WriteBankLogStep2(p_reqStr);

//		Map<String, String> params = new HashMap<String, String>();

//		params.put("cgb_data", p_reqStr);
		p_reqStr = "cgb_data=" + p_reqStr;
		String res = HttpConnUtil.getHttpDocument(bankFront.serverIP, p_reqStr, 200000, getCharset());
//		String res = HttpClientUtil.executePost(, params, "GBK");
		WriteBankLogStep3(res);
		return new String[] { "", res };
	}

	private String[] sendToBankByHttp(String p_reqStr) throws Exception {
		WriteBankLogLn("2.提交银行的地址：" + bankFront.serverIP);

		String interactiveMode = getBankConfig().getValueAsString("interactiveMode");
		if ("no-terminal".equals(interactiveMode)) {
			// 签名
			int indexPre = p_reqStr.indexOf("<Message>");
			int indexPrefix = p_reqStr.indexOf("</Message>");
			String waitSignData = p_reqStr.substring(indexPre, indexPrefix + 10);
			String ownCertFilePath = com.fingard.dsp.DSPSet.replaceFilePath(getBankConfig().getValueAsString("ownCertFilePath")).replaceAll("\r|\n|\t", "");
			String signature = sm2WithSM3(waitSignData, ownCertFilePath);
			p_reqStr = p_reqStr.replace("</BEDC>", "<Signature><signatureMethod>SM2</signatureMethod><digestMethod>SM3</digestMethod><signedInfo>" + signature + "</signedInfo></Signature></BEDC>");
		}
		WriteBankLogStep2(p_reqStr);


		String res = HttpClientUtil.executeXml(bankFront.serverIP, p_reqStr);

		WriteBankLogStep3(res);

		return new String[] { "", res };
	}

	public void getContentLength(TcpReceiver p_receiver) throws Exception {
		if (p_receiver.contentLength == -1) {
			String tmpCharset = getCharset();
			String tmpRecNow = new String(p_receiver.recBytes, 0, p_receiver.readedLength, tmpCharset);
			if (tmpRecNow.indexOf("</BEDC>") >= 0) {
				p_receiver.contentLength = p_receiver.readedLength;
				p_receiver.contentStartIndex = 0;
			}
		}
	}
}
